console.log("--------JavaScript中的5种基本数据类型--------");
console.log("1  字符串型  ");
console.log("2   数值型  ");
console.log("3   布尔型  ");
console.log("4   null型  ");
console.log("5  undefined型  ");
console.log("-------- 除以上五种类型之外的，都被称为 Object 型 --------");
console.log(
  " JavaScript 支持值与对象的隐式变换，所以有时可认为两者是完全相同的，而这会导致理解混乱。 "
);
console.log(
  " 同时，JavaScript 的变量没有类型之分，所以值和对象之间的区别就变得更为模糊了。"
);
console.log(" 像 Java 这样，变量具有数据类型的语言，被称为静态数据类型语言；");
console.log(
  " 而像 JavaScript 这样，变量没有类型的语言，则被称为动态数据类型语言。"
);

console.log("-------- 基本数据类型和引用类型 --------");
console.log(
  "“基本数据类型变量”直接保存有数值等类型的数据的值，而“引用类型变量”则保存有对象的引用。"
);

console.log("-------- 原始值，即：JavaScript的 基本数据类型 --------");
console.log(
  " JavaScript 的字符串型是“原始值”，而 Java 的字符串型并不是“原始值”。 "
);
console.log(
  " JavaScript 的字符串型是“基本数据类型”，而 Java 的字符串型并不是“基本数据类型”。 "
);

console.log("-------- 字符串型 --------");
console.log(
  " \\n：换行 ，\\t：水平制表符 ，\\b：退格，\\r：换行，\\f：换页，\\v：垂直制表符，\\：反斜杠，’：反单引号"
);

var str = "abc\rdef";
console.log(str);

var s = "i'am satoshi_uma , 'NO.1' ";
console.log(s);
console.log("-------- 字符串型的运算 --------");

var s1 = "abc";
var s2 = "def";
var s3 = s1 + s2;
console.log(s3);

var s3 = "def";
s3 += "abc";
console.log(s3);

var t = "012";
var t1 = t;
t += "345 ";
console.log(t);
console.log(t1);
console.log(typeof t);

console.log("-------- 字符串型的比较 --------");
console.log(" === 或者 == , !== 或者 != ");
console.log(" === 在比较的时候不会对数据类型进行转换，称其为严格相等。");
console.log(" > , >= , < , <= ;字符串值的比较是基于Unnicode字符的编码值 ");
console.log(" 字符串值大小的比较 ");

var w = "012";
var w2 = "0";
var w3 = w2 + "12";
console.log(w == w3);
console.log(w === w3);
console.log(w !== w3);
console.log(w != w3);

var ww = "abc";
var ww2 = "def";
console.log(ww < ww2);

console.log("-------- 字符串类 String类 --------");

var q = "abc";
console.log("字符串长度：" + q.length + " ");
console.log("字符串长度：" + "abc".length + ' | "abc".length 属于内建类型 ');

console.log("-------- 字符串对象 --------");

var sobj = new Object("abc");

var e = sobj + "def";
console.log(e);

var sobj1 = new Object("abc");
var sobj2 = new Object("abc");

console.log(" === 在比较的时候不会对数据类型进行转换，称其为严格相等。");
console.log(sobj1 == sobj2); // 虽然字符串内容相同，但并非引用了同一个对象，所以结果为false。
console.log(sobj1 === sobj2); // 虽然字符串内容相同，但并非引用了同一个对象，所以结果为false。

console.log(
  'sobj1 + " " == sobj2 + " " | == 不会进行隐式类型转换：' +
    (sobj1 + " " == sobj2 + " ")
); // 通过 +号 与空字符进行相接，就会进行隐式类型转换，转成字符串值
console.log(
  'sobj1 + " " === sobj2 + " " |  === 不会进行隐式类型转换：' +
    (sobj1 + " " === sobj2 + " ")
);

// console.log(" == 在比较的时候会对数据类型进行转换。");

var robj = new Object("abc");
var rr = "abc";
console.log("== 会进行隐式类型转换: " + (robj == rr));
console.log(
  "如果比较两个的大小，那么比较的是其内容，这时 “字符串值” 和 “字符串对象” 没有区别！"
);

var s = "abc";
// charAt() 返回指定索引处的字符。
console.log(s.charAt(0));
console.log("abc".charAt(2));

console.log("-------- 字符类型转换 --------");

var num = 47;
var s = String(num);
console.log(s);
console.log(typeof num);

// charCodeAt() 返回指定索引处的字符编码。
console.log(rr.charCodeAt(0));

var mms = "abcdefghi";
console.log(mms[0]);
console.log("abcdefghi"[4]);

var ns = new String("satoshi_uma");
// toUpperCase 将字符串中的所有字母字符转换为大写字母。
var ns2 = ns.toUpperCase();
console.log(ns2);

// 即使JavaScript独有的 [] 运算也不会改写字符串的内容。
ns[0] = "tt";
console.log(ns2);

var num = 0.1;
var num2 = 0.2;
console.log("相加结果为：" + (num + num2)); // 结果为 0.30000000000000004 并不是 0.3

console.log("-------- 数值型 --------");
console.log(" 0 , 51 为整数 ");
console.log(" -51 为负整数 ");
console.log(" 0.14 ,3.14 为实数 ");
console.log(
  " 对于整数来说，53位范围内都能得出争取的结果，如果使用53位以内整数的话是不会有任何问题的！"
);

console.log(typeof (1).toString());

// Number.MAX_VALUE
console.log("最大正值：" + Number.MAX_VALUE);
// Number.MIN_VALUE
console.log("最小正值：" + Number.MIN_VALUE);

console.log("正无穷大：" + Number.POSITIVE_INFINITY);
console.log("负无穷大：" + Number.NEGATIVE_INFINITY);
console.log("Not a Number：" + Number.NaN);

console.log("-------- NaN --------");
console.log(" 对 NaN 进行任何运算结果都是NaN ");

console.log(" NaN == NaN 或 NaN === NaN 的等值运算都为假。");
console.log("NaN == NaN的值：" + (NaN == NaN));
console.log("NaN === NaN的值：" + (NaN === NaN));

console.log(" isNaN ");
console.log("isNaN(NaN) 结果为：" + isNaN(NaN));
console.log("isNaN({}) 结果为：" + isNaN({}));

console.log(" isFinite ");
console.log(" -- isFinite 确定所提供的数字是否为有限值 -- ");
// isFinite 确定所提供的数字是否为有限值
console.log("isFinite(1) 结果为：" + isFinite(1));
console.log("isFinite(NaN) 结果为：" + isFinite(NaN));
console.log("isFinite(Infinity) 结果为：" + isFinite(Infinity));

console.log("-------- 布尔值 --------");
console.log(" === 在比较的时候不会对数据类型进行转换，称其为严格相等。");
console.log(true.toString());

var t = new Boolean(true);
console.log("==比较结果为：" + (t == true));
console.log("===比较结果为：" + (t === true));

console.log("-------- null型 --------");
console.log("null类型为：" + typeof null);
console.log("-------- undefined型 --------");
console.log("undefined类型为：" + typeof undefined);

var u;
console.log("未定义的u类型为：" + typeof u);
// undefined.toString(); // TypeError: Cannot read property 'toString' of undefined 不能读取未定义的 toString属性

console.log("-------- Object类型 --------");

var obj = {}; // 生成的空对象
console.log("生成的空对象类型为：" + typeof obj);

console.log("-------- 数据类型转换 --------");

console.log(" 字符串转换为数值 ");
console.log(typeof Number("100")); // 将字符串值 '100' 转换为数值 100
// number
console.log(Number("100x"));
// NaN
console.log(parseInt("100"));
// 100
console.log(parseInt("100x"));
// 100
console.log(parseInt("x"));
// NaN

/**
 * 将一个字符串转换为一个整数。
 * 一个要转换为数字的字符串。
 * 一个介于 2 和 36 之间的值，用于指定 numString 中数字的基数。
 * 如果没有提供这个参数，前缀为'0x'的字符串将被视为十六进制。
 * 所有其他的字符串都被认为是十进制的。
 */
console.log(parseInt("ff", 16));
// 255
console.log(parseInt("0xff", 16));
// 255
console.log(parseInt("ff", 10));
// NaN
console.log(parseInt("0.1"));
// 0
console.log(parseFloat("0.1"));
// 0.1

console.log(" -- 减法运算 ，可以将字符串值隐式转换成数值型。 -- ");
console.log("减法运算:" + ("100" - 1));
console.log("减法运算:" + ("98" - "1"));
console.log("减法运算:" + ("98" - ""));

console.log(" -- 但加法运算 ，不一定获得期望的运算结果。 -- ");
console.log("加法运算:" + ("100" + 1)); // 结果为：1001
console.log("加法运算:" + (1 + "100")); // 结果为：1100

console.log("-------- 从数值转换为字符串值 --------");
console.log(typeof String(100)); // 将数值 100 转换为字符串值 '100'
// string
console.log(typeof (100).toString()); // 将数值 100 转换为字符串值 '100'。为了区分小数点和点运算符而必须使用括号
// string
var n = 100;
console.log(String(n)); // 将数值 n 转换为字符串值
// 100
console.log(n.toString());

var n = 3;
console.log(typeof (n + "")); // 将数值转换为字符串

var s = "2";
console.log(typeof +s); // 将字符串转为数值

var nn = 0.003;
console.log(nn.toString().split("."));

console.log("-------- 转换为布尔型 --------");

console.log(" -- Object类型在被转为布尔类型之后结果必为true --");

var b = new Boolean(false);
if (b) {
  console.log("T");
} else {
  console.log("F");
}
// T
var z = new Number(0);
if (z) {
  console.log("T");
} else {
  console.log("F");
}
// T
var s = new String("");
if (s) {
  console.log("T");
} else {
  console.log("F");
}
// T

console.log(
  " -- 通过调用函数的方式获得的结果就和我们预期的一样，不再是Object类型，而是内建类型了。 --"
);

var b = Boolean(false);
if (b) {
  console.log("T");
} else {
  console.log("F");
}
// F
var z = Number(0);
if (z) {
  console.log("T");
} else {
  console.log("F");
}
// F
var s = String("");
if (s) {
  console.log("T");
} else {
  console.log("F");
}
// F
console.log("-------- 从Object类型转为基本数据类型 --------");

var NSObject = new Object();
console.log(typeof String(NSObject));

var NSObject1 = new Object();
console.log(typeof Number(NSObject1));

var NSObject2 = new Object();
console.log(typeof Boolean(NSObject2));

console.log("------------------------");
var NSObiect = {};

NSObject.toString = function () {
  return "MyObj";
};
console.log(NSObject.toString());
console.log(typeof NSObject);

console.log("-------- 从基本数据类型转为 Object 类型 --------");
// 字符串型         String 对象
// 数值型           Number 对象
// 布尔型           Boolean 对象
// null型          Error 对象
// undefined型     Error 对象

var obj = {};
console.log(obj);
console.log(typeof obj++);
